from xml.etree.cElementTree import parse
import pymunk as pm
import pygame
from pygame.color import *

GameObjects = []
RemoveObjects = []

def flipyv(p):
    """Small hack to convert pymunk to pygame coordinates"""
    return int(p.x), int(-p.y+600)

def getType(name):
    global GameObject
    return GameObject.COLLISION_TYPES.index(name.upper())

class GameObject:
    """Loads the level file information and creates the GameObjects"""
    COLLISION_TYPES = ['HERO'] 
    def __init__(self, space, tag):
        shape = tag.get("shape")
        mass = float(tag.get("mass"))
        self.shape = None 
        shape_options = shape.split(':')
        shape = shape_options[0]
        if shape == "circle":
            d = tag.get("d").split(' ')[:4]
            (cx, cy) = map(float, d[1].split(','))
            (rx, ry) = map(float, d[3].split(','))
            moment = pm.moment_for_circle(mass, 0, rx)
            if mass < 0:
                body = pm.Body(pm.inf, pm.inf)
            else:
                body = pm.Body(mass, moment)
            body.position = flipyv(pm.Vec2d((cx, cy)))
            self.shape = pm.Circle(body, rx)
        elif shape == "line":
            d = tag.get("d").split(' ')
            (x1, y1) = map(float, d[1].split(','))
            (x2, y2) = map(float, d[len(d)-1].split(','))
            body = pm.Body(pm.inf, pm.inf)
            self.shape = pm.Segment(body, (x1, 600-y1), (x2, 600-y2), 0.0)
        elif shape == "rect":
            (x, y) = (float(tag.get('x')), float(tag.get('y')))
            (w, h) = (float(tag.get('width')), float(tag.get('height')))
            y = 600 - y
            box_pts = map(pm.Vec2d, [(x-w/2, y-h/2), (x-w/2, y+h/2), (x+w/2, y+h/2), (x+w/2, y-h/2)])
            moment = pm.moment_for_poly(mass, box_pts, pm.Vec2d(0,0))
            if mass < 0:
                body = pm.Body(pm.inf, pm.inf)
            else:
                body = pm.Body(mass, moment)
            body.position = pm.Vec2d((x-w/2, y))
            self.shape = pm.Poly(body,box_pts, pm.Vec2d(0,0)) 
        indx = -1
        try:
            indx = GameObject.COLLISION_TYPES.index(tag.get("name").upper())
        except:
            GameObject.COLLISION_TYPES.append(tag.get("name").upper())
            indx = GameObject.COLLISION_TYPES.index(tag.get("name").upper())
                         
        self.shape.collision_type = indx
        self.shape.elasticity = 1
        try:
            if shape_options[1] == "ghost": #falls through objects but gives collision info
                self.shape.sensor = True
            if shape_options[2]: #assume elasticity
                self.shape.elasticity = float(shape_options[2])
        except:
            #its ok if we get out of index here
            pass
        if mass < 0:
            space.add_static(self.shape)
        else:
            space.add(self.shape.body, self.shape)
        self.shape.data = self


    def draw(self, screen):
        if hasattr(self.shape, 'radius'):
           #circle or segment
            if hasattr(self.shape,'a') and hasattr(self.shape,'b'):
                #segment
                body = self.shape.body
                pv1 = body.position + self.shape.a.rotated(body.angle)
                pv2 = body.position + self.shape.b.rotated(body.angle)
                p1 = flipyv(pv1)
                p2 = flipyv(pv2)
                pygame.draw.lines(screen, THECOLORS["lightgray"], False, [p1,p2])
            else:
                #circle
                p = flipyv(self.shape.body.position)
                pygame.draw.circle(screen, THECOLORS["blue"], p, int(self.shape.radius), 2)
        else:
            body = self.shape.body
            ps = self.shape.get_points()
            ps.append(ps[0])
            ps = map(flipyv, ps)
            color = THECOLORS["green"]
            pygame.draw.lines(screen, color, False, ps)
 
def LoadLevel(fname, space):
    global GameObjects
    GameObjects  = []
    fp = open(fname)
    tree = parse(fp)
    fp.close()
    e = tree._root.getchildren()[3]
    if e.tag.endswith('g'):
        for child in e.getchildren():
            GameObjects.append(GameObject(space, child))
